package bg.code.commons.plugin.ui;

import bg.code.commons.builder.idea.ProjectPluginConfig;
import bg.code.commons.builder.project.ToolConfigurationData;
import bg.code.commons.builder.utils.Strings;
import bg.code.commons.builder.vo.GenerateConfig;
import com.intellij.ide.actions.OpenProjectFileChooserDescriptor;
import com.intellij.ide.util.PackageChooserDialog;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiPackage;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBPanel;
import com.intellij.ui.components.JBTextField;
import com.intellij.ui.components.panels.HorizontalBox;
import com.intellij.ui.components.panels.VerticalBox;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import static bg.code.commons.plugin.Cons.*;

/**
 * @author 郑兴泉 956607644@qq.com
 * @data 2020/3/16
 * 描述：配置页面
 */
public class ConfigDialog extends DialogWrapper {

    // 配置文件
    private ProjectPluginConfig pluginConfig;

    /*** 类型选择 **/
    private JBLabel typeLabel;
    private JBCheckBox controllerCheckBox;
    private JBCheckBox serviceCheckBox;
    private JBCheckBox viewCheckBox;
    private JBCheckBox localeCheckBox;
    private JBCheckBox forceCheckBox;

    /*** html 模板目录 **/
    private JBLabel templatePathLabel;
    private TextFieldWithBrowseButton templatePathTextField;

    /*** 模板文件选择 */
    private JBLabel templateDirectoryLabel;
    private JComboBox templateEngine;


    private JBLabel baseModelPathLabel;

    private JBLabel basePathLabel;
    private JBLabel baseComPathLabel;
    private JBLabel baseNbPathLabel;
    private JBLabel baseUriLabel;
    private JBLabel basePackageLabel;
    private JBLabel modPackageLabel;
    private JBLabel serPackageLabel;
    private JBLabel serImplPackageLabel;
    /*** action 层路径 **/
    private JBLabel ctrPackageLabel;

    /*** 资源文件 **/
    private JBLabel localeI18nLabel;
    private TextFieldWithBrowseButton localeI18nPathTextField;

    private TextFieldWithBrowseButton basePathTextField;
    private TextFieldWithBrowseButton baseComPathTextField;
    private TextFieldWithBrowseButton baseNbPathTextField;
    private TextFieldWithBrowseButton baseModelPathTextField;


    private JBTextField baseUriTextField;
    private JBTextField basePackageTextField;
    private JBTextField modPackageTextField;
    private JBTextField serPackageTextField;
    private JBTextField serImplPackageTextField;
    private JBTextField ctrPackageTextField;

    // 基本路径
    private final String basePath;
    // 基本路径
    private final String baseModelPath;
    // 接口类路径
    private final String baseCommonPath;
    // 接口实现类路径
    private final String baseServicesPath;
    // web类路径
    private final String baseWebPath;
    // 资源文件类路径
    private final String baseLocalPath;

    // 文件所在包
    private final String basePackage;
    private final String basePerPackage;
    // 访问 url 路径
    private final String baseUri;
    private final String modelPackageName;
    private final String entityName;

    public ConfigDialog(ProjectPluginConfig pluginConfig) {
        super(pluginConfig.getProject());
        this.pluginConfig = pluginConfig;
        this.entityName = this.pluginConfig.getmClass().getName();

        System.out.println(this.entityName);
        System.out.println(pluginConfig.getmClass().getQualifiedName());

        String[] arr = pluginConfig.getmClass().getQualifiedName().split("\\.");
        this.basePackage = pluginConfig.getmClass().getQualifiedName().replace("." + arr[(arr.length - 2)] + "." + arr[(arr.length - 1)], "");
        this.basePerPackage = pluginConfig.getmClass().getQualifiedName().replace("." + arr[(arr.length - 4)] + "." + arr[(arr.length - 3)] + "." + arr[(arr.length - 2)] + "." + arr[(arr.length - 1)], "");
        this.modelPackageName = arr[(arr.length - 2)];
        // url 地址
        this.baseUri = (BASE_URI_PREV + this.modelPackageName + "/" + Strings.uncapitalize(this.entityName));
        this.basePath = pluginConfig.getPsiFile().getVirtualFile().getCanonicalPath();
        this.baseModelPath = getSplitByVal(this.basePath, "/com").replaceAll("\\/^", "");
        this.baseCommonPath = replaceAll(this.baseModelPath, "entity", "common");
        this.baseServicesPath = replaceAll(this.baseModelPath, "entity", "service-sys");
        this.baseWebPath = replaceAll(this.baseModelPath, "entity", "web-platform");
        this.baseLocalPath = replaceAll(this.baseWebPath, "java", "resources/locales");

        setupViews(pluginConfig.getmClass().getName());
        init();
    }

    private String getSplitByVal(String replace, String splitVal) {
        if (replace.contains(splitVal)) {
            return replace.split(splitVal)[0];
        }
        return replace;
    }

    private String replaceAll(String oldVal, String oldReplace, String newReplace) {
        return oldVal.replaceAll(oldReplace, newReplace);
    }


    private void setupViews(String modelName) {
        setTitle(String.format("%s:%s", MODEL_NAME, modelName));


        this.typeLabel = new JBLabel(TYPE_CHOOSE_TEXT);
        this.controllerCheckBox = new JBCheckBox(CONTROLLERS_CHECKBOX, true);
        this.serviceCheckBox = new JBCheckBox(SERVICES_CHECKBOX, true);
        this.viewCheckBox = new JBCheckBox(VIEWS_CHECKBOX, true);
        this.localeCheckBox = new JBCheckBox(LOCALES_CHECKBOX, true);
        this.forceCheckBox = new JBCheckBox(REPLACE_TEXT_CHECKBOX, false);

        this.templateDirectoryLabel = new JBLabel(TEMPLATE_TYPE);
        this.templateEngine = new JComboBox(new Object[]{BEETL_TEMPLATE, VELOCITY_TEMPLATE});

        this.templatePathLabel = new JBLabel(TEMPLATE_DIRECTORY);
        this.templatePathTextField = new TextFieldWithBrowseButton(new JBTextField());
        this.templatePathTextField.setText(pluginConfig.getConfiguration().getTemplatePath());


        this.modPackageLabel = new JBLabel(MODELS_PACKAGE);
        this.baseModelPathTextField = new TextFieldWithBrowseButton(new JBTextField(this.baseModelPath));


        this.baseComPathTextField = new TextFieldWithBrowseButton(new JBTextField(this.baseCommonPath));
        this.baseNbPathTextField = new TextFieldWithBrowseButton(new JBTextField(this.baseServicesPath));
        this.basePathTextField = new TextFieldWithBrowseButton(new JBTextField(this.baseWebPath));
        this.localeI18nPathTextField = new TextFieldWithBrowseButton(new JBTextField(this.baseLocalPath));

        this.templatePathTextField.setEditable(false);
        this.baseModelPathTextField.setEditable(false);
        this.baseComPathTextField.setEditable(false);
        this.baseNbPathTextField.setEditable(false);
        this.basePathTextField.setEditable(false);
        this.localeI18nPathTextField.setEditable(false);


        addChoosePathActionListener(this.templatePathTextField, TEMPLATE_DIRECTORY, null);
        addChoosePathActionListener(this.baseModelPathTextField, BASE_MODEL_PATH, this.baseModelPath);
        addChoosePathActionListener(this.baseComPathTextField, BASE_COMMON_PATH, this.baseCommonPath);
        addChoosePathActionListener(this.baseNbPathTextField, BASE_COMMON_IMPL_PATH, this.baseServicesPath);
        addChoosePathActionListener(this.basePathTextField, BASE_WEB_PATH, this.baseWebPath);
        addChoosePathActionListener(this.localeI18nPathTextField, LOCALE_I18N_PATH, this.baseLocalPath);


        this.baseUriTextField = new JBTextField(this.baseUri);
        this.basePackageTextField = new JBTextField(this.basePackage);
        this.baseModelPathLabel = new JBLabel(BASE_MODEL_PATH);
        this.baseComPathLabel = new JBLabel(BASE_COMMON_PATH);
        this.baseNbPathLabel = new JBLabel(BASE_COMMON_IMPL_PATH);
        this.basePathLabel = new JBLabel(BASE_WEB_PATH);
        this.baseUriLabel = new JBLabel(BASE_URI);
        this.basePackageLabel = new JBLabel(BASE_PACKAGE);
        this.localeI18nLabel = new JBLabel(LOCALE_I18N_PATH);


        this.serPackageLabel = new JBLabel(SERVICES_PACKAGE);
        this.serImplPackageLabel = new JBLabel(SERVICES_IMPL_PACKAGE);
        this.ctrPackageLabel = new JBLabel(CONTROLLERS_PACKAGE);

        this.modPackageTextField = new JBTextField(this.basePackage + "." + this.modelPackageName);
        this.modPackageTextField.setEditable(false);
        this.serPackageTextField = new JBTextField(this.basePackage + "." + this.modelPackageName + ".services");
        this.serImplPackageTextField = new JBTextField(this.basePackage + "." + this.modelPackageName + ".services.impl");
        this.ctrPackageTextField = new JBTextField(this.basePackage + ".web.modules.platform." + this.modelPackageName);

    }


    private void addChoosePathActionListener(final TextFieldWithBrowseButton withBrowseButton, final String title, String root) {
        withBrowseButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                OpenProjectFileChooserDescriptor descriptor = new OpenProjectFileChooserDescriptor(false, false);
                descriptor.setHideIgnored(true);
                if (Strings.isNotBlank(root)) {
                    descriptor.setShowFileSystemRoots(false);
                    descriptor.setRoots(new VirtualFile[]{LocalFileSystem.getInstance().findFileByPath(pluginConfig.getProject().getBasePath())});
                } else {
                    descriptor.setShowFileSystemRoots(true);
                }
                descriptor.setTitle(title);
                FileChooser.chooseFiles(descriptor, pluginConfig.getProject(), root == null ? null : LocalFileSystem.getInstance().findFileByPath(root), (virtualFiles) -> {
                    VirtualFile virtualFile = (VirtualFile) virtualFiles.get(0);
                    String selectPath = virtualFile.getCanonicalPath();
                    selectPath = selectPath.replace("\\\\", "/").replace("\\", "/");
                    withBrowseButton.setText(selectPath);
                });
            }
        });
    }

    private void addCheckBoxActionListener(final JBCheckBox checkBox, final JBPanel panel) {
        checkBox.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (checkBox.isSelected()) {
                    panel.setVisible(true);
                } else {
                    panel.setVisible(false);
                }
            }
        });
    }

    private void addChoosePackageActionListener(final TextFieldWithBrowseButton withBrowseButton, final String title, String basepackagePath) {
        withBrowseButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                final PackageChooserDialog dialog = new PackageChooserDialog(title, pluginConfig.getPsiFile().getProject());
                dialog.selectPackage(withBrowseButton.getText());
                dialog.show();
                final PsiPackage aPackage = dialog.getSelectedPackage();
                withBrowseButton.setText(aPackage.getQualifiedName());
            }
        });
    }

    // 重写下面的方法，返回一个自定义的swing样式，该样式会展示在会话框的最下方的位置
    @Nullable
    @Override
    protected JComponent createSouthPanel() {
        JComponent southPanel = super.createSouthPanel();
        if (null == southPanel) {
            return null;
        }
        VerticalBox root = new VerticalBox();

        root.add(this.baseModelPathLabel);
        root.add(this.baseModelPathTextField);
        root.add(this.baseComPathLabel);
        root.add(this.baseComPathTextField);
        root.add(this.baseNbPathLabel);
        root.add(this.baseNbPathTextField);
        root.add(this.basePathLabel);
        root.add(this.basePathTextField);
        root.add(this.localeI18nLabel);
        root.add(this.localeI18nPathTextField);
        root.add(this.baseUriLabel);
        root.add(this.baseUriTextField);
        root.add(this.basePackageLabel);
        root.add(this.basePackageTextField);


        root.add(this.serPackageLabel);
        root.add(this.serPackageTextField);
        root.add(this.serImplPackageLabel);
        root.add(this.serImplPackageTextField);
        root.add(this.ctrPackageLabel);
        root.add(this.ctrPackageTextField);
        root.add(this.forceCheckBox);
        root.add(southPanel);
        return root;
    }

    // 重写下面的方法，返回一个自定义的swing样式，该样式会展示在会话框的中央位置
    @Nullable
    @Override
    protected JComponent createCenterPanel() {

        JComponent centerPanel = super.createContentPane();

        VerticalBox root = new VerticalBox();

        root.add(this.typeLabel);

        HorizontalBox box = new HorizontalBox();
        box.add(this.controllerCheckBox);
        box.add(this.serviceCheckBox);
        box.add(this.localeCheckBox);
        box.add(this.viewCheckBox);

        root.add(box);

        root.add(this.templateDirectoryLabel);
        root.add(this.templateEngine);

        root.add(this.templatePathLabel);
        root.add(this.templatePathTextField);

        root.add(centerPanel);
        return root;
    }

    private GenerateConfig getGenerateConfig() {
        GenerateConfig config = new GenerateConfig();

        config.setController(this.controllerCheckBox.isSelected());
        config.setService(this.serviceCheckBox.isSelected());
        config.setLocale(this.localeCheckBox.isSelected());
        config.setView(this.viewCheckBox.isSelected());
        config.setForce(this.forceCheckBox.isSelected());

        config.setTemplateType(this.templateEngine.getSelectedItem().toString());
        config.setTemplatePath(this.templatePathTextField.getText().trim());


        config.setBasePackage(this.basePackage);
        config.setEntityName(this.entityName);
        config.setBaseModelPath(this.baseModelPathTextField.getText().trim());
        config.setBasePath(this.basePathTextField.getText().trim());
        config.setBaseCommonPath(this.baseComPathTextField.getText().trim());
        config.setBaseNbPath(this.baseNbPathTextField.getText().trim());
        config.setBaseUri(this.baseUriTextField.getText().trim());


        config.setEntityPackageName(this.modPackageTextField.getText().trim());
        config.setServicePackageName(this.serPackageTextField.getText().trim());
        config.setServiceFileName("I" + this.entityName + "Services");
        config.setServiceImplPackageName(this.serImplPackageTextField.getText().trim());
        config.setServiceImplFileName(this.entityName + "ServicesImpl");
        config.setControllerPackageName(this.ctrPackageTextField.getText().trim());
        config.setControllerFileName(this.entityName + "Controllers");
        return config;
    }

    private void validation(String value, String title) {
        if (Strings.isBlank(value)) {
            Messages.showErrorDialog(title, "错误提示");
            return;
        }
    }

    @Override
    protected void doOKAction() {
        ToolConfigurationData configuration = pluginConfig.getConfiguration();
        if (Strings.isBlank(configuration.getTemplatePath())) {
            Messages.showErrorDialog("请先设置模板目录", "错误提示");
            return;
        }
//        else {
//            Path path = Paths.get(configuration.getTemplatePath());
//            File[] list = path.toFile().listFiles();
//            File[] var11 = list;
//            int var12 = list.length;
//
//            for(int var13 = 0; var13 < var12; ++var13) {
//                File file = var11[var13];
//                if (!file.isFile()) {
//                    this.templateSelect.addItem(file.getName());
//                }
//            }
//        }
        PreviewData dialog = null;
        try {
            pluginConfig.setConfiguration(configuration);
            dialog = new PreviewData(pluginConfig, getGenerateConfig());
        } catch (Exception ex) {
            ErrorDialog.createError(this.pluginConfig.getProject(), ex.getMessage());
            return;
        }
        dialog.show();
        if (!dialog.isOK()) {
            return;
        }
        super.doOKAction();
        super.doCancelAction();
    }

    public ProjectPluginConfig getPluginConfig() {
        return pluginConfig;
    }

    public void setPluginConfig(ProjectPluginConfig pluginConfig) {
        this.pluginConfig = pluginConfig;
    }
}
